package com.fingard.dsp.bank.directbank.chinaums01;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringEscapeUtils;

import com.alibaba.fastjson.JSONObject;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.bankInterface.IOtherElse;
import com.fingard.dsp.bank.directbank.chinaums01.util.MacUtil;
import com.fingard.dsp.bank.reqrespobj.otherelse.ReqOtherElse;
import com.fingard.dsp.bank.reqrespobj.otherelse.RetAtsOtherElse;
import com.fingard.text.MD5SaltHelper;
import com.fingard.text.StringHelper;

public class ChinaUMS01OtherElse extends ChinaUMS01Base implements IOtherElse {
	@Override
	public RetAtsOtherElse d_else(ReqOtherElse p_reqElse) throws Exception {
		if ("VerifySign".equals(p_reqElse.reqHeader.transType)) { // 统一下单异步通知
			return verifyChinaUMS(p_reqElse);
		} else if ("PosQuery".equals(p_reqElse.reqHeader.transType)) { // POS查询
			if ("PQ01".equals(p_reqElse.reqHeader.commandCode)) {
				return verifyPosQuery(p_reqElse);
			} else {
				return signPosQuery(p_reqElse);
			}
		} else if ("PosNotify".equals(p_reqElse.reqHeader.transType)) { // POS通知
			if ("PS01".equals(p_reqElse.reqHeader.commandCode)) {
				return verifyPosNotify(p_reqElse);
			} else {
				return signPosNotify(p_reqElse);
			}
		} else if ("PosAuth".equals(p_reqElse.reqHeader.transType)) { // POS实名
			if ("PA01".equals(p_reqElse.reqHeader.commandCode)) {
				return verifyPosAuth(p_reqElse);
			} else {
				return signPosAuth(p_reqElse);
			}
		} if ("UnifiedSign".equals(p_reqElse.reqHeader.transType)) {
			if ("POS".equals(p_reqElse.reqHeader.commandCode)) {
				return unifiedSignForPos(p_reqElse);
			}
		} else {
			RetAtsOtherElse retAts = new RetAtsOtherElse(p_reqElse.reqHeader);
			
			retAts.retHashMap = new HashMap<String, String>();
			retAts.retHashMap.put("RespCode", "-1");
			retAts.retHashMap.put("RespInfo", "未知的TransType：" + p_reqElse.reqHeader.transType);
			
			return retAts;
		}
		
		return null;
	}
	
	public RetAtsOtherElse verifyChinaUMS(ReqOtherElse p_reqElse) {
		RetAtsOtherElse retAts = new RetAtsOtherElse(p_reqElse.reqHeader);
		retAts.retHashMap = new HashMap<String, String>();
		
		try {
			String ownAct = "";
			if (p_reqElse.reqHashMap.containsKey("OurBankAccount")) {
				ownAct = p_reqElse.reqHashMap.get("OurBankAccount");
			}
			
			String merchantId = "";
			if (p_reqElse.reqHashMap.containsKey("MchId")) {
				merchantId = p_reqElse.reqHashMap.get("MchId");
			}
			
			String appId = "";
			if (p_reqElse.reqHashMap.containsKey("AppId")) {
				appId = p_reqElse.reqHashMap.get("AppId");
			}
			
			String plain = "";
			if (p_reqElse.reqHashMap.containsKey("Plain")) {
				plain = StringEscapeUtils.unescapeHtml(p_reqElse.reqHashMap.get("Plain"));
			} else {
				retAts.retHashMap.put("RespCode", "-1");
				retAts.retHashMap.put("RespInfo", "缺失验签原始串");
				return retAts;
			}

			ActSetItem actItem = getBankConfig().getActSetItemByAny(ownAct, merchantId, appId, "unifiedorder");
			if (actItem != null) {
				String[] tmpStrRet = getChinaUMSSign(plain, actItem.saltKey);
				
				WriteBankLogLn2("2.待签名数据:\r\n" + tmpStrRet[0]);
				WriteBankLogLn("3.1 银联签名:" + tmpStrRet[1]);
				
				boolean verifySignResult = verifyWithMd5(tmpStrRet[0], tmpStrRet[1]);
				if (verifySignResult) {
					retAts.retHashMap.put("RespCode", "0");
					retAts.retHashMap.put("RespInfo", "验签通过");
				} else {
					retAts.retHashMap.put("RespCode", "-1");
					retAts.retHashMap.put("RespInfo", "验签失败");
				}
			} else {
				retAts.retHashMap.put("RespCode", "-1");
				retAts.retHashMap.put("RespInfo", "未找到账号[" + ownAct + "]商户配置信息");
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			retAts.retHashMap.put("RespCode", "-1");
			retAts.retHashMap.put("RespInfo", ex.getMessage());
			WriteBankLogLn(ex);
		}

		return retAts;
	}
	
	public RetAtsOtherElse verifyPosAuth(ReqOtherElse p_reqElse) {
		RetAtsOtherElse retAts = new RetAtsOtherElse(p_reqElse.reqHeader);
		retAts.retHashMap = new HashMap<String, String>();
		
		try {
			String plain = "";
			if (p_reqElse.reqHashMap.containsKey("ReqMsg")) {
				plain = p_reqElse.reqHashMap.get("ReqMsg");
			} else {
				retAts.retHashMap.put("RespCode", "-1");
				retAts.retHashMap.put("RespInfo", "缺失'ReqMsg'!");
				return retAts;
			}
			
			String sign = plain.substring(148);
			WriteBankLogLn2("POS原始签名:" + sign);
			String signData = plain.substring(4, 148);
			String mac = MacUtil.getMac(signData.getBytes(getPOSCharset()));
			WriteBankLogLn2("本机签名:" + mac);
			if (sign.equals(mac)) {
				String askNumber = plain.substring(43, 61).trim();
				String seqNoCheck = plain.substring(61, 69).trim();
				
				JSONObject result = new JSONObject();
				result.put("Rdseq", askNumber);
				result.put("RdseqAuthCode", seqNoCheck);
				result.put("ReserveField", signData);
				result.put("PayAccount", plain.substring(83, 143).trim());
				result.put("PayType", plain.substring(143, 144).trim());
				result.put("TerminalType", plain.substring(144, 148).trim());
				result.put("Reserved01", "");
				result.put("Reserved02", "");
				
				retAts.retHashMap.put("RespCode", "0");
				retAts.retHashMap.put("RespInfo", "验签通过");
				retAts.retHashMap.put("Result", result.toJSONString());
			} else {
				retAts.retHashMap.put("RespCode", "-1");
				retAts.retHashMap.put("RespInfo", "验签失败!");
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			retAts.retHashMap.put("RespCode", "-1");
			retAts.retHashMap.put("RespInfo", ex.getMessage());
			WriteBankLogLn(ex);
		}

		return retAts;
	}
	
	public RetAtsOtherElse signPosAuth(ReqOtherElse p_reqElse) {
		RetAtsOtherElse retAts = new RetAtsOtherElse(p_reqElse.reqHeader);
		retAts.retHashMap = new HashMap<String, String>();
		
		try {
			String plain = "";
			if (p_reqElse.reqHashMap.containsKey("ReqMsg")) {
				plain = p_reqElse.reqHashMap.get("ReqMsg");
			} else {
				retAts.retHashMap.put("RespCode", "-1");
				retAts.retHashMap.put("RespInfo", "缺失原始串'ReqMsg'");
				return retAts;
			}
			
			StringBuilder sbContent = new StringBuilder();
			sbContent.append("0300");
			
			JSONObject reqJson = JSONObject.parseObject(plain);
			String reserveField = reqJson.getString("ReserveField");
			sbContent.append(String.format("%-12s", reserveField.substring(4, 16)));// 银行代码
			sbContent.append(String.format("%-15s", reserveField.substring(16, 31)));// 商户号
			sbContent.append(String.format("%-8s", reserveField.substring(31, 39)));// 终端号
			sbContent.append(String.format("%-18s", reserveField.substring(39, 57))); // 业务流水号
			sbContent.append(String.format("%-8s", reserveField.substring(57, 65)));// 支付校验码
			sbContent.append(String.format("%-14s", reserveField.substring(65, 79)));// 交易时间
			sbContent.append(String.format("%-60s", reserveField.substring(79, 139)));// 支付账号
			sbContent.append(String.format("%-1s", reserveField.substring(139, 140)));// 支付方式
			sbContent.append(reqJson.getString("AuthResult"));// 实名认证结果
			sbContent.append(String.format("%-60s", reqJson.getString("PaymentNo")));// 支付单号
			String terminalType = reqJson.getString("TerminalType");
			if (StringHelper.isNullOrEmpty(terminalType)) {
				terminalType = reserveField.substring(140, 144);
			}
			sbContent.append(String.format("%-4s", terminalType)); // 终端类型
			String result = String.format("%4s", sbContent.toString().getBytes("GBK").length + 8).replace(' ', '0') + sbContent.toString();
			
			retAts.retHashMap.put("RespCode", "0");
			retAts.retHashMap.put("RespInfo", "");
			retAts.retHashMap.put("Result", result);
		} catch (Exception ex) {
			ex.printStackTrace();
			retAts.retHashMap.put("RespCode", "-1");
			retAts.retHashMap.put("RespInfo", ex.getMessage());
			WriteBankLogLn(ex);
		}

		return retAts;
	}
	
	public RetAtsOtherElse verifyPosQuery(ReqOtherElse p_reqElse) {
		RetAtsOtherElse retAts = new RetAtsOtherElse(p_reqElse.reqHeader);
		retAts.retHashMap = new HashMap<String, String>();
		
		try {
			String plain = "";
			if (p_reqElse.reqHashMap.containsKey("ReqMsg")) {
				plain = p_reqElse.reqHashMap.get("ReqMsg");
			} else {
				retAts.retHashMap.put("RespCode", "-1");
				retAts.retHashMap.put("RespInfo", "缺失'ReqMsg'!");
				return retAts;
			}
			
			String sign = plain.substring(87);
			WriteBankLogLn2("POS原始签名:" + sign);
			String signData = plain.substring(4, 87);
			String mac = MacUtil.getMac(signData.getBytes(getPOSCharset()));
			WriteBankLogLn2("本机签名:" + mac);
			if (sign.equals(mac)) {
				String askNumber = plain.substring(43, 61).trim();
				String seqNoCheck = plain.substring(61, 69).trim();
				
				String refundFlag = "false";
				String transType = plain.substring(4, 8);
				if (!"0100".equals(transType)) {
					refundFlag = "true";
				} 
				
				JSONObject result = new JSONObject();
				result.put("Rdseq", askNumber);
				result.put("RdseqAuthCode", seqNoCheck);
				result.put("IsRefund", refundFlag);
				result.put("ReserveField", signData);
				
				retAts.retHashMap.put("RespCode", "0");
				retAts.retHashMap.put("RespInfo", "验签通过");
				retAts.retHashMap.put("Result", result.toJSONString());
			} else {
				retAts.retHashMap.put("RespCode", "-1");
				retAts.retHashMap.put("RespInfo", "验签失败!");
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			retAts.retHashMap.put("RespCode", "-1");
			retAts.retHashMap.put("RespInfo", ex.getMessage());
			WriteBankLogLn(ex);
		}

		return retAts;
	}
	
	public RetAtsOtherElse signPosQuery(ReqOtherElse p_reqElse) {
		RetAtsOtherElse retAts = new RetAtsOtherElse(p_reqElse.reqHeader);
		retAts.retHashMap = new HashMap<String, String>();
		
		try {
			String plain = "";
			if (p_reqElse.reqHashMap.containsKey("ReqMsg")) {
				plain = p_reqElse.reqHashMap.get("ReqMsg");
			} else {
				retAts.retHashMap.put("RespCode", "-1");
				retAts.retHashMap.put("RespInfo", "缺失原始串'ReqMsg'");
				return retAts;
			}
			
			JSONObject reqJson = JSONObject.parseObject(plain);
			
			StringBuilder sbContent = new StringBuilder();
			
			String reserveField = reqJson.getString("ReserveField");
			
			String transType = reserveField.substring(0, 4);
			if ("0100".equals(transType)) {
				transType = "0101";
			} else {
				transType = "0111";
			}
			sbContent.append(transType);// 交易类型
			sbContent.append(String.format("%-12s", reserveField.substring(4, 16)));// 银行代码
			sbContent.append(String.format("%-15s", reserveField.substring(16, 31)));// 商户号
			sbContent.append(String.format("%-8s", reserveField.substring(31, 39)));// 终端号
			sbContent.append(String.format("%-18s", reserveField.substring(39, 57))); // 业务流水号
			sbContent.append(String.format("%-8s", reserveField.substring(57, 65)));// 支付校验码
			String amount = reqJson.getString("Amount");
			if (StringHelper.hasAnyChar(amount)) {
				amount = StringHelper.amountMultiply100(amount);
			}
			sbContent.append(String.format("%12s", amount).replace(' ', '0')); // 交易金额 以分为单位，左补零
			sbContent.append(Format.DateTime14Format.format(new Date())); // 交易时间(yymmddhhmmss)
			sbContent.append(String.format("%-4s", reserveField.substring(79, 83)));// 终端类型
			sbContent.append(reqJson.getString("ReturnCode"));
			
			String insurer = reqJson.getString("Insurer");
			if (insurer.getBytes("GBK").length >= 20) {
				sbContent.append(cutCountLen(insurer, 20));
			} else {
				sbContent.append(buildLen(insurer, 20));
			}
			
			String authFlag = reqJson.getString("RealNameAuth"); 
			if ("1".equals(authFlag)) {
				sbContent.append("Y"); 
			} else if ("2".equals(authFlag)) {
				sbContent.append("X");
			} else {
				sbContent.append("N");
			}
			
			String payName = reqJson.getString("BankAccountName");
			if (payName.getBytes("GBK").length >= 20) {
				sbContent.append(cutCountLen(payName, 20));
			} else {
				sbContent.append(buildLen(payName, 20));
			}
			
			sbContent.append(String.format("%-2s", getBankConfig().getMapValueByKey("certTypePOSMapping", reqJson.getString("CertType"))));
			sbContent.append(String.format("%-30s", reqJson.getString("CertNumber")));
			sbContent.append(String.format("%-11s", reqJson.getString("CellPhone")));
//			String mac = MacUtil.getMac(sbContent.toString().getBytes("GBK"));
			String result = String.format("%4s", sbContent.toString().getBytes("GBK").length + 8).replace(' ', '0') + sbContent.toString();
			
			retAts.retHashMap.put("RespCode", "0");
			retAts.retHashMap.put("RespInfo", "");
			retAts.retHashMap.put("Result", result);
		} catch (Exception ex) {
			ex.printStackTrace();
			retAts.retHashMap.put("RespCode", "-1");
			retAts.retHashMap.put("RespInfo", ex.getMessage());
			WriteBankLogLn(ex);
		}

		return retAts;
	}
	
	public RetAtsOtherElse verifyPosNotify(ReqOtherElse p_reqElse) {
		RetAtsOtherElse retAts = new RetAtsOtherElse(p_reqElse.reqHeader);
		retAts.retHashMap = new HashMap<String, String>();
		
		try {
			String plain = "";
			if (p_reqElse.reqHashMap.containsKey("ReqMsg")) {
				plain = StringEscapeUtils.unescapeHtml(p_reqElse.reqHashMap.get("ReqMsg"));
			} else {
				retAts.retHashMap.put("RespCode", "-1");
				retAts.retHashMap.put("RespInfo", "缺失原始串'ReqMsg'");
				return retAts;
			}
			
			// 1、验签
			String sign = plain.substring(180);
			WriteBankLogLn2("POS原始签名:" + sign);
			String signData = plain.substring(4, 180);
			String mac = MacUtil.getMac(signData.getBytes(getPOSCharset()));
			WriteBankLogLn2("本机签名:" + mac);
			if (sign.equals(mac)) {
				// 组装返回数据
				String askNumber = plain.substring(43, 61).trim();
				
				String refundFlag = "false";
				String transType = plain.substring(4, 8);
				if (!"0200".equals(transType)) {
					refundFlag = "true";
				} 
				
				JSONObject result = new JSONObject();
				result.put("Rdseq", askNumber);
				result.put("IsRefund", refundFlag);
				result.put("ReserveField", signData);
				result.put("PayState", "success");
				result.put("PayInfoCode", "S0000");
				result.put("PayInfo", "S0000-支付成功");
				result.put("Amount", StringHelper.amountDivide100(plain.substring(69, 81).trim()));
				result.put("PayType", plain.substring(179, 180));
				result.put("Asknumber", plain.substring(114, 144).trim());
				result.put("Abstracts", plain.substring(114, 144).trim());
				result.put("PayMadeDate", plain.substring(81, 95));
				result.put("TerminalCode", plain.substring(35, 43).trim());
				result.put("MerchantID", plain.substring(20, 35).trim());
				result.put("OppBankAccount", plain.substring(95, 114).trim());
				result.put("OppBankCode", plain.substring(8, 20).trim());
				result.put("Reserved01", "");
				result.put("Reserved02", "");
				
				retAts.retHashMap.put("RespCode", "0");
				retAts.retHashMap.put("RespInfo", "验签通过");
				retAts.retHashMap.put("Result", result.toJSONString());
			} else {
				retAts.retHashMap.put("RespCode", "-1");
				retAts.retHashMap.put("RespInfo", "验签失败!");
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			retAts.retHashMap.put("RespCode", "-1");
			retAts.retHashMap.put("RespInfo", ex.getMessage());
			WriteBankLogLn(ex);
		}

		return retAts;
	}
	
	public RetAtsOtherElse signPosNotify(ReqOtherElse p_reqElse) {
		RetAtsOtherElse retAts = new RetAtsOtherElse(p_reqElse.reqHeader);
		retAts.retHashMap = new HashMap<String, String>();
		
		try {
			String plain = "";
			if (p_reqElse.reqHashMap.containsKey("ReqMsg")) {
				plain = p_reqElse.reqHashMap.get("ReqMsg");
			} else {
				retAts.retHashMap.put("RespCode", "-1");
				retAts.retHashMap.put("RespInfo", "缺失原始串'ReqMsg'");
				return retAts;
			}
			
			JSONObject reqJson = JSONObject.parseObject(plain);
			
			StringBuilder sbContent = new StringBuilder();
			String reserveField = reqJson.getString("ReserveField");
			sbContent.append(reserveField.substring(0, 4));// 交易类型
			sbContent.append(reserveField.substring(4, 16));// 银行代码
			sbContent.append(reserveField.substring(16, 31));// 商户号
			sbContent.append(reserveField.substring(31, 39));// 终端号
			sbContent.append(reserveField.substring(39, 57)); // 业务流水号
			sbContent.append(reserveField.substring(57, 65));// 业务流水号校验码
			sbContent.append(reserveField.substring(65, 77)); // 交易金额 以分为单位，左补零
			sbContent.append(reserveField.substring(77, 91)); // 交易时间(yymmddhhmmss)
			sbContent.append(reserveField.substring(91, 110));// 缴费卡号
			sbContent.append(reserveField.substring(110, 140));// 银行流水号
			sbContent.append(reserveField.substring(140, 144)); // 清算日期(MMDD)
			sbContent.append(reserveField.substring(144, 150));// 交易流水号
			sbContent.append(reserveField.substring(150, 170));// 检索参考号
			sbContent.append(reserveField.substring(170, 174));// 终端类型
			sbContent.append(reserveField.substring(174, 175));// 交易处理类型
			sbContent.append(String.format("%-20s", reqJson.getString("PolicyCode")));// 投保单号PolicyCode
			sbContent.append(reqJson.getString("ReturnCode"));// 核心处理结果
			
//			String mac = MacUtil.getMac(sbContent.toString().getBytes(getPOSCharset()));
			
			String result = String.format("%4s", sbContent.toString().getBytes("GBK").length + 8).replace(' ', '0') + sbContent.toString();
			
			retAts.retHashMap.put("RespCode", "0");
			retAts.retHashMap.put("RespInfo", p_reqElse.reqHashMap.get("ReturnMsg"));
			retAts.retHashMap.put("Result", result);
		} catch (Exception ex) {
			ex.printStackTrace();
			retAts.retHashMap.put("RespCode", "-1");
			retAts.retHashMap.put("RespInfo", ex.getMessage());
			WriteBankLogLn(ex);
		}

		return retAts;
	}
	
	/**
	 * POS保单信息查询签名
	 * 
	 * @param p_reqElse
	 * @return
	 */
	public RetAtsOtherElse unifiedSignForPos(ReqOtherElse p_reqElse) {
		RetAtsOtherElse retAts = new RetAtsOtherElse(p_reqElse.reqHeader);
		retAts.retHashMap = new HashMap<String, String>();

		try {
			Map<String, String> mapParams = p_reqElse.reqHashMap;
			mapParams = removeHead(mapParams);

			String tmpSignData = getSignStr(mapParams);
			tmpSignData += "&key=" + getBankConfig().getValueAsString("saltKey");
			WriteBankLogLn2("待签名数据:\r\n" + tmpSignData);
			String sign = MD5SaltHelper.md5(tmpSignData, getCharset("UTF-8", "pos"));
			WriteBankLogLn2("签名结果:"+sign);
			if (StringHelper.hasAnyChar(sign)) {
				retAts.retHashMap.put("RespCode", "0");
				retAts.retHashMap.put("RespInfo", "");
				retAts.retHashMap.put("Result", sign);
			} else {
				retAts.retHashMap.put("RespCode", "-1");
				retAts.retHashMap.put("RespInfo", "签名失败!");
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			retAts.retHashMap.put("RespCode", "-1");
			retAts.retHashMap.put("RespInfo", ex.getMessage());
			WriteBankLogLn(ex);
		}

		return retAts;
	}
}
